.TITLE LPDRV - RSX-11M-PLUS LINE PRINTER DRIVER .SBTTL LPDRV - DESCRIPTION AND HISTORY .IDENT /13.03/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; ; B. S. MCCARTHY 13-AUG-81 ; ; BASED ON THE ORIGINAL NOVEL BY D. N. CUTLER, AND THE ; ORIGINAL KMC LP DRIVER FOR RSX11M, BY YOURS TRULY. ; ; ; MODIFIED FOR RSX-11M-PLUS VERSION 3.0 BY: ; ; J. W. BERZLE ; ; MODIFIED FOR RSX-11M-PLUS VERSION 4.0 BY: ; ; B. S. MCCARTHY 26-FEB-86 13.02 ; ; BM380 -- CONVERT TO USE EXEC VECTORING ; ; B. S. MCCARTHY 26-FEB-86 13.03 ; ; BM388 -- FIX REGISTER USAGE IN VECTOR ; TRANSLATE ROUTINE ; ; ; LP11/LS11/LA180 LINE PRINTER CONTROLLER DRIVER ; WITH KMC-11 DMA SUPPORT ; .PAGE .SBTTL . - MACRO LIBRARY CALLS/DEFINITIONS ; ; MACRO LIBRARY CALLS ; .MCALL ABODF$, HWDDF$, PKTDF$, UCBDF$ .MCALL SCBDF$ ABODF$ ; DEFINE TASK ABORT CODES HWDDF$ ; DEFINE HARDWARE REGISTERS PKTDF$ ; DEFINE I/O PACKET OFFSETS UCBDF$ ; DEFINE UCB OFFSETS SCBDF$ ,,SYSDEF ; DEFINE VARIABLE SCB OFFSETS ; ; EQUATED SYMBOLS ; ; SOME OF THESE DEFINITIONS ARE INCLUDED FOR INFORMATION ONLY ; AND ARE NOT REFERENCED IN THE DRIVER ; ; LINE PRINTER STATUS WORD BIT DEFINITIONS (U.CW2) ; LS11 = 100000 ; LS11 PRINTER (1=YES) CRJT = 40000 ; CARRIAGE RETURN JUST OUTPUT (1=YES) FORM = 20000 ; FORM FEED REQUIRED (1=YES) CRTY = 10000 ; CARRIAGE RETURN REQUIRED (1=YES) ABRT = 4000 ; ABORT REQUEST IF HUNG (1=YES) LFCT = 3000 ; UNPROCESSED LINE FEED COUNT FIELD LFBT = 1000 ; UNPROCESSED LINE FEED ADD/SUB BIT BHLD = 400 ; BYTE HELD BACK FOR CARRIAGE RETURN (1=YES) OFFL = 200 ; PRINTER OFFLINE (1=YES) LOWER = 100 ; LOWER CASE (1=YES) PWRFLG = 40 ; POWER FAIL RECOVERY IN PROGRESS RQINPR = 20 ; REQUEST IN PROGRESS WHEN POWER FAILED KNOWN = 10 ; PRINTER KNOWN TO KMC-11 (1=YES) BLCT = 7 ; UNPROCESSED BLANK COUNT FIELD BLBT = 1 ; UNPROCESSED BLANK ADD/SUB BIT ; ; LINE PRINTER HORIZONAL POSITION AND HELD BACK BYTE (U.CW3) ; HORPS = 0 ; HORIZONAL POSITION HELDB = 1 ; BYTE HELD BACK ; ; DEFINE TIMEOUT WITH NO ERROR BIT IN S.STS FOR LP ; TMONO=200 ; 1=TIMEOUT WITH NO ERROR ; ; K.PRM STATUS BITS ; KMCLOA = 1 ; KMC-11 MICROCODE LOADED KPKMC = 2 ; THIS IS A KMC KRB .PAGE .SBTTL . - KMC11 SPECIFIC DATA DEFINITIONS ; KMC-11/COMM-IOP-LP BIT DEFINITIONS ; KMC CSR WORD 0 (SEL0) RUN = 100000 ; RUN BIT (1=KMC RUNNING) MC = 40000 ; MASTER CLEAR (SET TO 1 TO CLEAR KMC) RQI = 200 ; REQUEST INPUT (SET TO REQUEST KMC INPUT_ IEO = 20 ; OUTPUT INTERRUPT ENABLE (SET TO ENABLE) IEI = 1 ; INPUT INTERRUPT ENABLE (SET TO ENABLE) ; KMC CSR WORD 1 (SEL2) PRTNUM = 3400 ; PRINTER NUMBER MASK RDYO = 200 ; READY OUTPUT (1=READY) RDYI = 20 ; READY INPUT (1=READY) FNCBSI = 3 ; BASE IN FUNCTION FNCCTI = 1 ; CONTROL IN FUNCTION FNCBAI = 0 ; BUFFER ADDRESS IN FUNCTION ; KMC CSR WORD 2 (SEL4) POLCNT = 177400 ; POLLING COUNT FOR BASE IN FUNCTION ; KMC CSR WORD 3 (SEL6) KOPKOE = 200 ; KILL ON ERROR OPTION (FOR CONTROL IN) KOPNXT = 40 ; DON'T EXPAND TABS OPTION KOPVTL = 20 ; CONVERT VT TO LF OPTION KOPDRN = 10 ; DISCARD RUBOUTS/NULLS OPTION KOPDNP = 4 ; DISCARD NON-PRINTING CHARACTERS OPTION KOPLUC = 2 ; CONVERT LOWER TO UPPER CASE OPTION KOPFPR = 1 ; FAST PRINTER OPTIMIZATIONS OPTION KMCABF = 10 ; KILL (ABORT) FINISHED ON CONTROL OUT KMCNXM = 6 ; NON-EXISTENT MEMORY (WE CAN'T GET THIS?) KMCONL = 4 ; PRINTER ERROR CONDITION CLEAR KMCOFL = 2 ; PRINTER ERROR OCCURED (PAPER JAM,ETC.) BEXT = 140000 ; BUS EXTENSION BITS FOR BUFF. ADDR. IN KILASN = 20000 ; KILL ASSIGN BIT KILL = 10000 ; KILL BIT ; BUFFER DESCRIPTOR BITS LASTBF = 100000 ; LAST DESCRIPTOR IN LIST ; ; DEFINE THE SYMBOL "L$$PRN" EITHER IN THE RSXMC.MAC CONDITIONAL ; ASSEMBLY FILE FOR YOUR SYSTEM OR REMOVE THE SEMICOLON (;) FROM ; THE LINE CONTAINING THE SYMBOL IN THE KMC LINE PRINTER DRIVER ; (LKDRV). ; ;L$$PRN=0 ; SYMBOL TO PASS RUBOUTS/NULLS ; VC$LP = 0 ; VECTORED LP DRIVER. ; ; LOCAL DATA ; .IF DF K$$MLP ; KMC LINE PRINTER SUPPORT KMCCTB: .WORD 0 ; ADDRESS OF $KMCTB IN CTB UNITPF: .WORD 0 ; THIS IS A UNIT POWERFAIL .ENDC ; DF K$$MLP ; ; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER) ; CNTBL: .BLKW L$$P11 ; ADDRESS OF UNIT CONTROL BLOCK ; EXECUTIVE VECTOR AREA EXEVEC: .WORD 0 ; VECTOR FLAG (<>0 -> VECTOR ALREADY TRANSLATED) KISA6:: .WORD KISAR6 DVMSG:: .WORD $DVMSG FORK:: .WORD $FORK GTPKT:: .WORD $GTPKT .IF NDF LD$LP INTSV:: .WORD $INTSV .ENDC ; NDF LD$LP IODON:: .WORD $IODON MPUBM:: .WORD $MPUBM SCERR:: .WORD $SCERR STMAP:: .WORD $STMAP ULDRQ:: .WORD $ULDRQ EXEVCL=<<<.-EXEVEC>/2>-1> ; ; DRIVER DISPATCH TABLE - DDT$ CAN'T GENERATE THIS ONE ; $LPTBL:: ; START OF DRIVER DISPATCH TABLE .WORD LPINI ; D.VINI - INITIATION ENTRY POINT .WORD LPCAN ; D.VCAN - CANCEL ENTRY POINT .WORD LPOUT ; D.VTIM - TIMEOUT ENTRY POINT .WORD LPPWF ; D.VPWF - POWERFAIL RECOVERY ENTRY .IF DF K$$MLP .WORD LPKRB ; D.VKRB - KRB STATUS CHANGE ENTRY .WORD LPUCB ; D.VUCB - UCB STATUS CHANGE ENTRY .IFF .WORD LPPWF ; D.VPWF - NO KRB STATUS CHANGE ENTRY .WORD LPPWF ; D.VPWF - NO UCB STATUS CHANGE ENTRY .ENDC ; DF K$$MLP ; D.VINT - START OF INTERRUPT VECTOR ; CONTROL INFORMATION .ASCII /LP/ ; FOR "LP" CONTROLLERS .WORD $LPINT ; SINGLE INTERRUPT ENTRY POINT .WORD 0 ; VECTOR TABLE TERMINATOR LPCTB: .WORD $LPCTB ; POINTER TO CTB KRB TABLE .IF DF K$$MLP .ASCII /KM/ ; FOR "KM" CONTROLLERS .WORD $LKINP ; TWO INTERRUPT VECTORS, .WORD $LKOUT ; ONE UNUSED ($LKINP) .WORD 0 ; VECTOR TABLE TERMINATOR KMCTB: .WORD $KMCTB ; POINTER TO CTB KRB TABLE .ENDC ; DF K$$MLP $LPTBE::.WORD 0 ; END OF DISPATCH TABLE .PAGE .SBTTL LPINI - LINE PRINTER CONTROLLER INITIATOR ;+ ; **-LPINI-LP11/LS11 LINE PRINTER CONTROLLER INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST ; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE EXECU- ; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ATTEMPT ; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER IS ; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER- ; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; OUTPUTS: ; ; IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WAIT- ; ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OPER- ; ATION IS INITIATED. ;- .ENABL LSB LPINI: GTPKT$ LP,L$$P11,,CNTBL,T ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1=ADDRESS OF THE I/O REQUEST PACKET. ; R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3=CONTROLLER INDEX. ; R4=ADDRESS OF THE STATUS CONTROL BLOCK. ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; LINE PRINTER I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD. ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER. ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTER TASK. ; WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTER TASK HEADER. ; WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTER TASK HEADER (UCB). ; WD. 05 -- I/O FUNCTION CODE (IO.WLB). ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK. ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK. ; WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000). ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE. ; WD. 12 -- RELOCATION BIAS OF I/O BUFFER. (I.PRM) ; WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER. ; WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED. ; WD. 15 -- CARRIAGE CONTROL BYTE. ; WD. 16 -- NOT USED. ; WD. 17 -- NOT USED. ; WD. 20 -- NOT USED. ; .IF DF K$$MLP BIT #KP.OFL,S.KTB+2(R4) ; VERIFY PORT IS ONLINE BNE 5$ ; IF NE, IT'S OFFLINE MOV S.KTB+2(R4),R0 ; GET ADDRESS OF KMC11 BEQ 5$ ; IF EQ, THIS PRINTER NOT ON KMC BIT #KMCLOA,K.PRM(R0) ; IS THE MICROCODE LOADED FOR THE KMC ? BNE LKINI ; IF NE, MICROCODE IS LOADED .ENDC ; DF K$$MLP 5$: MOV R5,R3 ; CALCULATE ADDRESS OF PRINTER STATUS WORD ADD #U.CW2,R3 ; BIC #FORM!CRTY!ABRT!LFCT!BHLD!BLCT,(R3) ; CLEAR STATUS BITS MOVB I.PRM+6(R1),R0 ; GET CARRIAGE CONTROL BYTE BEQ LPIN1 ; IF EQ, NO CARRIAGE CONTROL CMPB #'$,R0 ; CARRIAGE RETURN AT END OF LINE? BEQ 10$ ; IF EQ, NO BIS #CRTY,(R3) ; SET FOR CARRIAGE RETURN AT AND OF LINE 10$: CMPB #'+,R0 ; LINE FEED AT BEGINNING OF LINE? BEQ LPIN1 ; IF EQ, NO CMPB #'1,R0 ; FORM FEED AT BEGINNING OF LINE? BNE 20$ ; IF NE, NO ADD #FORM-LFBT,(R3) ; SET FOR FORM FEED AT BEGINING OF LINE 20$: ADD #LFBT,(R3) ; ADD IN ONE LINE FEED CMPB #'0,R0 ; DOUBLE SPACE? BNE LPIN1 ; IF NE, NO ADD #LFBT,(R3) ; ADD IN ONE LINE FEED LPIN1: CALL LPRNT ; FILL LINE PRINTER BUFFER BCS 35$ ; IF CS, REQUEST NOT FINISHED MOV S.PKT(R4),R1 ; GET ADDRESS OF I/O PACKET MOV I.PRM+4(R1),R1 ; GET NUMBER OF BYTES PROCESSED MOV #IS.SUC&377,R0 ; SET SUCCESSFUL STATUS CALL @IODON ; FINISH I/O OPERATION BR LPINI ; 35$: BITB #TMONO,S.STS(R4) ; TIMEOUT NO ERROR BIT SET? BEQ 40$ ; IF EQ, NO MOVB #2,S.CTM(R4) ; SET TIME OUT COUNT TO 2 (MIN. 1 SEC.) BR 41$ ; SKIP 40$: MOVB S.ITM(R4),S.CTM(R4) ; RESET DEVICE TIMEOUT COUNT 41$: MOV @S.KRB(R4),R4 ; GET CSR ADDRESS BISB #100,(R4) ; ENABLE PRINTER INTERRUPT RETURN .DSABL LSB .PAGE .SBTTL LKINI - KMC11 PRINTER INITIALIZATION ENTRY POINT ;+ ; **-LKINI-LP11/LS11 WITH KMC-11 LINE PRINTER CONTROLLER INITIATOR ;- .IF DF K$$MLP LKINI: MOV R5,CNTBL(R3) ; SAVE ADDRESS OF REQUEST UCB BIC #ABRT,U.CW2(R5) ; CLEAR REQUEST ABORTED ; ; CONVERSION OF ADDRESS FOR A NPR DEVICE ; ; ON AN 18-BIT MACHINE, THEN ; U.BUF = HIGH ORDER 2 BITS OF PHYSICAL ADDRESS IN BITS 4 AND 5 ; U.BUF+2 = LOW ORDER 16 BITS OF PHYSICAL ADDRESS. ; ON AN 11/70, THEN ; U.BUF = HIGH ORDER 6 BITS OF PHYSICAL ADDRESS IN HIGH BYTE. ; U.BUF+2 = LOW ORDER 16 BITS OF PHYSICAL ADDRESS. MOV R1,-(SP) ; SAVE R1 MOV R2,-(SP) ; AND R2 MOV U.BUF(R5),R1 ; RELOCATION BIAS MOV U.BUF+2(R5),R2 ; DISPLACEMENT ADDRESS ASL R2 ; REMOVE APR6 BIAS FROM DISPLACEMENT ASL R2 ; CLC ; GET 2 BITS OF RELOCATION BIAS ROR R1 ; RORB R2 ; TO FILL 8 LOW ORDER BITS OF ADDRESS ASR R1 ; RORB R2 ; SWAB R2 ; SWAP TO COLLECT 8 MORE BITS BISB R1,R2 ; INSERT UPPER 8 BITS OF ADDRESS SWAB R2 ; SWAP BACK TO REAL ADDRESS CLRB R1 ; CLEAR LOW BYTE OF UPPER BITS .IF NDF M$$EXT ASH #-4,R1 ; PUT BITS <17:18> OF ADDRESS INTO ; BITS <4:5> .ENDC MOV R1,U.BUF(R5) ; HIGH ORDER BITS MOV R2,U.BUF+2(R5) ; LOW ORDER 16 BITS OF PHYS. ADDRESS MOV (SP)+,R2 ; RESTORE R2 MOV (SP)+,R1 ; AND R1 .IF DF M$$MGE&M$$EXT CALL @STMAP ; SETUP UNIBUS MAP .ENDC ; M$$MGE&M$$EXT ; TEST TO SEE IF KMC KNOW'S ABOUT THIS PRINTER ; AND ISSUE BASE IN IF NECESSARY LKIN1: BIT #KNOWN,U.CW2(R5) ; PRINTER KNOWN ? BNE 10$ ; IF NE, YES CALL WTKMC ; WAIT FOR KMC READY MOV @S.KRB(R4),6(R0); FILL IN CSR ADDRESS MOV #L$$KPC*256.,4(R0) ; SET UP POLLING COUNT CLR R4 ; SCRATCH FOR UNIT/FUNCTION BISB U.UNIT(R5),R4 ; SET UNIT NUMBER SWAB R4 ; PUT IT IN HIGH BYTE BIS #FNCBSI,R4 ; SET BASE IN FUNCTION MOV R4,2(R0) ; AND ISSUE FUNCTION MOV U.SCB(R5),R4 ; RESTORE SCB ADDRESS BIS #KNOWN,U.CW2(R5) ; SET PRINTER KNOWN ; TEST TO SEE IF PRINTER HAS BEEN INITIALIZED FOR CORRECT WIDTH ; (CURRENT SET WIDTH IN U.CW3) 10$: CMPB U.CW4(R5),U.CW3(R5) ; BUF SIZE CURRENT WIDTH ? BEQ 20$ ; IF EQ, YES, CONTROL IN WAS ISSUED CALL WTKMC ; WAIT FOR KMC READY .IF NDF L$$PRN MOV #KOPDRN,R4 ; SET FUNCTION TO DISCARD RUBOUTS/NULLS .IFF CLR R4 ; SET FUNCTION TO PASS RUBOUTS/NULLS .ENDC BIT #LOWER,U.CW2(R5) ; LOWER CASE PRINTER BNE 11$ ; IF NE, LOWER CASE PRINTER BIS #KOPLUC,R4 ; SET LOWER TO UPPER CASE SUPPORT 11$: ; REF LABEL .IF DF L$$11R BIT #LS11,U.CW2(R5) ; FAST PRINTER ? BNE 12$ ; IF NE, NO BIS #KOPFPR,R4 ; SET FAST PRINTER OPTIMIZATIONS .ENDC ; DF L$$11R 12$: MOV R4,6(R0) ; SET OPTIONS WORD MOV U.CW4(R5),4(R0) ; SET PRINTER WIDTH CLR R4 ; SCRATCH FOR UNIT NUMBER/FUNCTION BISB U.UNIT(R5),R4 ; SET IN UNIT NUMBER SWAB R4 ; PUT IT IN HIGH BYTE BIS #FNCCTI,R4 ; SET CONTROL IN FUNCTION MOV R4,2(R0) ; ISSUE FUNCTION MOV U.SCB(R5),R4 ; RESTORE SCB ADDRESS MOVB U.CW4(R5),U.CW3(R5) ; SET PRINTER SIZE SET ; BUILD ADDRESS BUFFER IN I/O PACKET AND ISSUE REQUEST 20$: ; REFERENCE LABEL .IF DF M$$MGE & M$$EXT MOV R1,-(SP) ; SAVE I/O PACKET ADDRESS CALL @MPUBM ; MAP UNIBUS TO MEMORY MOV (SP)+,R1 ; RESTORE I/O PACKET ADDRESS .ENDC ; M$$MGE & M$$EXT CALL WTKMC ; WAIT FOR KMC READY MOV U.BUF+2(R5),I.PRM+10(R1) ; SET LOW PART OF BUFFER ADDR. MOV U.CNT(R5),I.PRM+12(R1) ; AND LENGTH OF BUFFER MOV U.BUF(R5),R0 ; GET HIGH TWO BITS OF ADDR. SWAB R0 ; PUT IN HIGH BYTE ASR R0 ; SHIFT INTO BITS 10/11 ASR R0 ; BIS #LASTBF,R0 ; SET FOR LAST FUNCTION BISB I.PRM+6(R1),R0 ; SET VFC BITS IN MOV R0,I.PRM+14(R1) ; STORE INTO BUFF ADDR DESC. ; BUFFER DESCRIPTOR BUILT IN WORDS 4,5,6 OF PARAM LIST MOV @S.KTB+2(R4),R0 ; POINT TO KMC CSR CLR 6(R0) ; CLEAR OUT KILL BITS MOV R1,R4 ; COPY PACKET ADDRESS ADD #I.PRM+10,R4 ; POINT TO BUFFER DESCRIPTOR MOV R4,4(R0) ; FILL IN BUFFER ADDRESS CLR R4 ; SCRATCH FOR UNIT NUMBER BISB U.UNIT(R5),R4 ; SET IN UNIT NUMBER SWAB R4 ; PUT IT IN HIGH BYTE MOV R4,2(R0) ; AND START TRANSFER 25$: RETURN ; EXIT FROM DRIVER .ENDC ; DF K$$MLP .PAGE .SBTTL LPPWF - LINE PRINTER POWERFAIL ENRTY POINT ; ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND THEREFORE CAUSES ; NO IMMEDIATE ACTION ON THE DEVICE. THIS IS DONE TO AVOID A RACE CONDITION ; THAT COUND EXIST IN RESTARTING THE I/O OPERATION ; LPPWF: .IF DF K$$MLP BCC 5$ ; BR IF CONTROLLER POWERFAIL INC UNITPF ; INDICATE UNIT POWERFAIL 5$: BIT #KP.OFL,S.KTB+2(R4) ; VERIFY PORT IS ONLINE BNE 10$ ; IF NE, IT'S OFFLINE MOV S.KTB+2(R4),R0 ; GET ADDRESS OF KMC11 BEQ 10$ ; IF EQ, THIS PRINTER NOT ON KMC BIT #KMCLOA,K.PRM(R0) ; IS THE MICROCODE LOADED FOR THE KMC? BEQ 10$ ; IF EQ, MICROCODE NOT LOADED JMP LKPWF ; DO POWERFAIL FOR LK 10$: MOV #0,UNITPF ; ZERO UNIT POWERFAIL FLAG .IFF ; DF K$$MLP CALL LPKRB ; TRANSLATE EXEC ENTRY POINT VECTOR .ENDC ; DF K$$MLP RETURN ; .PAGE .SBTTL LKPWF - KMC11 PRINTER POWERFAIL ENTRY POINT ; ; UNIT POWERFAIL PROCESSING MARKS A DEVICE AS UNKNOWN AND OF UNKNOWN ; WIDTH. FOR CONTROLLER POWERFAIL CALLS, THE MICROCODE IS MARKED AS ; NOT LOADED. THE MICROCODE LOADER (MCL...) IS REQUESTED. IF MCL... ; IS NOT INSTALLED AN ERROR MESSAGE IS ISSUED. IF THERE IS NO POOL, A ; RETURN IS EXECUTED AND LPDRV WILL NOT USE THE KMC. ; .IF DF K$$MLP .ENABL LSB LKPWF: TST UNITPF ; IS THIS A UNIT POWERFAIL? BEQ LKPWF0 ; IF EQ, CONTROLLER POWERFAIL DEC UNITPF ; SET BACK TO ZERO BIS #PWRFLG,U.CW2(R5) ; SET POWERFAIL IN PROGRESS TST CNTBL(R3) ; REQUEST IN PROGRESS BEQ 10$ ; IF EQ, NO BIS #RQINPR,U.CW2(R5) ; SET REQUEST IN PROGRESS FLAG 10$: BIC #KNOWN,U.CW2(R5) ; SET PRINTER UNKNOWN CLRB U.CW3(R5) ; AND SET THE WIDTH TO ZERO RETURN ; EXIT FROM DRIVER LKPWF0: ; CTB IS IN R3 MOV R2,R4 ; PUT KRB INTO R4 MOV #0,R5 ; MICROCODE FILENAME INDEX BIC #KMCLOA,K.PRM(R4) ; INDICATE MICROCODE NOT LOADED 13$: CALL @ULDRQ ; REQUEST LOADER BCC 15$ ; BR IF OK BEQ 20$ ; IF EQ, TASK MCL... NOT INSTALLED BNE 40$ ; IF NE, NO POOL 15$: MOV #MC,@(R4) ; MASTER CLEAR KMC-11 BR 40$ ; RETURN 20$: MOV #T.NKLF,R0 ; MESSAGE NUM "MICROCODE LOADER NOT ..." CALLR @DVMSG ; PRINT MESSAGE AND EXIT 40$: RETURN .ENDC ; DF K$$MLP .DSABL LSB .PAGE .SBTTL $LPINT - LINE PRINTER INTERRUPT HANDLING ENTRY ;+ ; **-$LPINT-LP11/LS11 LINE PRINTER CONTROLLER INTERUPTS ;- $LPINT:: ;;; REF LABEL INTSV$ LP,PR4,L$$P11,,CNTBL ;;; GENERATE INTERRUPT SAVE CODE MOV U.SCB(R5),R4 ;;; GET ADDRESS OF STATUS CONTROL BLOCK MOV @S.KRB(R4),R4 ;;; GET CSR ADDRESS CLRB (R4) ;;; DISABLE PRINTER INTERRUPTS CALL @FORK ;;; CREATE A SYSTEM PROCESS MOV U.SCB(R5),R4 ; GET SCB MOV @S.KRB(R4),R3 ; GET CSR ADDRESS TST (R3) ; PRINTER READY? BMI LPOUT1 ; IF MI, NO MOV R5,R3 ; CALCULATE ADDRESS OF PRINTER STATUS WORD ADD #U.CW2,R3 ; CALL LPRNT ; FILL LINE PRINTER BUFFER BCC LPINT1 ; IF CC, OPERATION FINISHED MOVB S.ITM(R4),S.CTM(R4) ; RESET DEVICE TIMEOUT COUNT MOV @S.KRB(R4),R4 ; GET CSR ADDRESS BISB #100,(R4) ; ENABLE PRINTER INTERRUPT RETURN LPINT1: MOV S.PKT(R4),R1 ; GET ADDRESS OF I/O PACKET MOV I.PRM+4(R1),R1 ; GET NUMBER OF BYTES PROCESSED MOV #IS.SUC&377,R0 ; SET SUCCESSFUL STATUS 60$: CALL @IODON ; FINISH I/O OPERATION JMP LPINI ; .PAGE .SBTTL $LKINT - KMC11 PRINTER INTERRUPT ENTRY POINT ;+ ; **-$LPINT-LP11/LS11 LINE PRINTER CONTROLLER INTERUPTS ; (INTERRRUPTS ARE FROM COMM IOP, NOT PRINTER) ; ; INPUT INTERRUPTS SHOULD NOT OCCUR, AND ARE THEREFORE ; DISMISSED IMMEDIATELY. ; ; OUTPUT INTERRUPTS ARE CAUSED FOUR WAYS: ; ; 1) - BUFFER ADDRESS OUT - INDICATES SUCCESSFUL COMPLETION ; OF AN OUTPUT OPERATION ; 2) - CONTROL OUT - KMCABF SET IN KCS3 - ABORT COMPLETED ; 3) - CONTROL OUT - KMCONL SET IN KCS3 - PREVIOUS ERROR CLEARED ; 4) - CONTROL OUT - OTHER - ERROR CONDITION ON PRINTER ;- .IF DF K$$MLP $LKINP:: ; IGNORE INPUT INTERRUPTS ; ($LPINP IS NEEDED TO MAKE DRIVER LOAD ; CORRECTLY) .IF NDF L$$DRV ! M$$MGE ! LD$LP RTI .IFF RETURN .ENDC .PAGE .ENABL LSB $LKOUT:: ;;; REF LABEL .IF NDF L$$DRV ! M$$MGE ! LD$LP JSR R5,@INTSV ;;; SINCE THERE'S ONE KMC VECTOR, .WORD ^C&PR7 ;;; NORMAL UCB CALC. DOESN'T WORK .ENDC ADD KMCCTB,R4 ;;; POINT INTO KRB ADD #10,R4 ;;; ADD DISPLACEMENT TO CTB TABLE MOV (R4),R4 ;;; GET KRB ADDRESS MOV R4,-(SP) ;;; SAVE KRB ADDRESS MOV (R4),R4 ;;; GET CSR ADDRESS MOV 2(R4),R5 ;;; GET PRINTER NUMBER FROM KMC BIC #^C,R5 ;;; STRIP OFF JUNK SWAB R5 ;;; INTO LOW HALF OF REG ASL R5 ;;; AND CREATE WORD INDEX MOV (SP)+,R4 ;;; GET KRB ADDRESS ADD K.OFF(R4),R5 ;;; ADD OFFSET TO KRB TABLE ADD R4,R5 ;;; ADD KRB ADDRESS MOV (R5),R5 ;;; GET UCB ADDRESS BEQ 90$ ;;; IF EQ, DISMISS SPURIOUS INTERRUPT MOV (R4),R4 ;;; GET KMC CSR MOV R5,-(SP) ;;; SAVE UCB ADDRESS MOV 6(R4),R5 ;;; GET PRINTER ERROR CODE SWAB R5 ;;; PUT INTO HIGH BYTE CLRB R5 ;;; CLEAR OUT LOW BYTE BISB 2(R4),R5 ;;; AND MERGE IN INTERRUPT CAUSE BIC #IEO,(R4) ;;; DISABLE KMC INTERRUPTS BIC #RDYO,2(R4) ;;; RELEASE KMC MOV R5,R4 ;;; INTERRUPT CAUSE/ERROR BYTE MOV (SP)+,R5 ;;; RESTORE UCB POINTER CALL @FORK ;;; CREATE A SYSTEM PROCESS MOV U.SCB(R5),R0 ; GET SCB MOV @S.KTB+2(R0),R0 ; GET KMC CSR BIS #IEO,(R0) ; RE-ENABLE KMC INTERRUPTS MOV R4,R0 ; COPY INTERRUPT CAUSE MOV R4,R1 ; COPY POSSIBLE ERROR BYTE SWAB R1 ; AND MOVE IT TO LOW BYTE MOV U.SCB(R5),R4 ; GET SCB BIT #1,R0 ; WAS IT A CONTROL OUT ? BNE 70$ ; IF NE, YES MOV #IS.SUC,R0 ; SET SUCCESS STATUS 60$: MOV S.PKT(R4),R1 ; GET I/O PACKET ADDRESS MOV I.PRM+4(R1),R1 ; GET REQUESTED BYTE COUNT CALL @IODON ; FINISH I/O OPERATION MOV U.SCB(R5),R4 ; GET SCB MOV S.KTB+2(R4),R4 ; GET KMC KRB MOVB K.CON(R4),R4 ; GET CONTROLLER INDEX CLR CNTBL(R4) ; CLEAR CONTROLLER TABLE JMP LPINI ; AND START DRIVER AGAIN 70$: CMPB #KMCABF,R1 ; ABORT FINISHED ? BNE 80$ ; IF NE, YES ABORT DONE LKOUT1: MOV #IE.ABO,R0 ; SET ABORT STATUS BR 60$ ; AND OUT NORMALLY 80$: CMPB #KMCONL,R1 ; PRINTER BACK NOW ? BNE LKOUT ; IF NE, NO, MUST BE ERROR RETURN ; ELSE YES, THAT'S NICE. 90$: MOV (R4),R4 ; GET CSR BIC #RDYO,2(R4) ; RELEASE KMC RETURN ; AND EXIT FROM DRIVER .DSABL LSB .ENDC ; DF K$$MLP .PAGE .SBTTL LPOUT - LINE PRINTER TIMEOUT ENTRY POINT ; ; DEVICE TIMEOUT RESULTS IN A NOT READY MESSAGE BEING OUTPUT AT ; A SYSGEN SPECIFIED INTERVAL. TIMEOUTS ARE CAUSED BY POWERFAILURE ; AND PRINTER FAULT CONDITIONS. ; .ENABL LSB LPOUT: .IF DF K$$MLP BIT #KP.OFL,S.KTB+2(R4) ;;; VERIFY PORT IS ONLINE BNE 10$ ;;; IF NE, IT'S OFFLINE MOV S.KTB+2(R4),R0 ;;; GET ADDRESS OF KMC11 BEQ 10$ ;;; IF EQ, THIS PRINTER NOT ON KMC BIT #KMCLOA,K.PRM(R0) ;;; IS THE MICROCODE LOADED FOR THE KMC? BEQ 10$ ;;; IF EQ, NO JMP LKOUT ;;; DO TIMEOUT FOR LK .ENDC ; DF K$$MLP 10$: MOV @S.KRB(R4),R3 ;;; GET CSR CLRB (R3) ;;; DISABLE PRINTER INTERRUPT MTPS #0 ;;; ALLOW INTERRUPTS LPOUT1: MOV R5,R3 ; CALCULATE ADDRESS MOV #IE.ABO&377,R0 ; ASSUME REQUEST IS TO BE ABORTED ADD #U.CW2,R3 ; ADJUST TO PRINTER STATUS WORD BIT #ABRT,(R3) ; ABORT REQUEST? BEQ 70$ ; IF EQ, NO CALL @IODON ; FINISH I/O OPERATION JMP LPINI ; 70$: MOV @S.KRB(R4),R2 ; GET CSR ADDRESS TST (R2) ; PRINTER READY? BMI DEVNR ; DEVICE NOT READY(ERROR BIT SET) BITB #TMONO,S.STS(R4) ; WAS TIMEOUT WITH NO ERROR BIT? BNE 71$ ; IF NE, YES BISB #TMONO,S.STS(R4) ; NO, SET THE BIT(TO CLEAR WHEN IODON) JMP LPIN1 ; GO BACK AND PRINT BUFFER 71$: BICB #TMONO,S.STS(R4) ; 2 TIMEOUTS WITH NO ERROR => ERROR BR DEVNR ; DEVICE NOT READY .DSABL LSB .PAGE .SBTTL LKOUT - KMC11 LINE PRINTER TIMEOUT ENTRY POINT ; ; TIMEOUT PROCESSING IS ENTERED FOR ANY OF THE FOLLOWING ; ; 1. FOLLOWING AN IO.KIL, IF THE REQUEST IS NOT COMPLETED ; NORMALLY BEFORE THE NEXT TIMEOUT CHECK, THEN A HARDWARE ; ABORT IS ISSUED HERE. ; ; 2. AFTER A DEVICE ERROR, THE TIMEOUT SECTION TAKES CARE OF ; ISSUING NOT READY MESSAGES. ; .IF DF K$$MLP LKOUT: MTPS #0 ;;; ALLOW INTERRUPTS BIT #PWRFLG,U.CW2(R5) ; POWERFAIL RECOVERY IN PROGRESS ? BEQ 99$ ; IF EQ, NO BIC #PWRFLG,U.CW2(R5) ; CLEAR POWERFAIL FLAG BIT #ABRT,U.CW2(R5) ; ABORT REQUESTED ? BNE LKOUT1 ; IF NE, YES, BUT REQUEST IS ALREADY ; ABORTED (AND HOW) DUE TO KMC FAILURE BIT #RQINPR,U.CW2(R5) ; REQUEST IN PROGRESS WHEN WE WENT DOWN ? BEQ 96$ ; IF EQ, NO BIC #RQINPR,U.CW2(R5) ; CLEAR REQUEST IN PROGRESS MOV S.PKT(R4),R1 ; RESTORE I/O PACKET ADDRESS JMP LKIN1 ; AND RESTART REQUEST 96$: CLRB S.STS(R4) ; CLEAR FAKE CONTROLLER BUSY BICB #US.BSY,U.STS(R5) ; AND DECLARE UNIT IDLE JMP LPINI ; TRY TO ACTIVATE CONTROLLER 99$: BIT #ABRT,U.CW2(R5) ; ABORT REQUESTED ? BEQ DEVNR ; IF EQ, NO CALL WTKMC ; WAIT TILL IT'S READY MOV #KILL,6(R0) ; SET KILL FUNCTION CLR 4(R0) ; NO BUFF ADDR CLR R1 ; SCRATCH FOR PRINTER NUMBER BISB U.UNIT(R5),R1 ; SET IN UNIT NUMBER SWAB R1 ; PUT IT IN HIGH BYTE MOV R1,2(R0) ; FILL IN PRINTER NUMBER AND START KILL RETURN ; WAIT TIL IT'S ALL OVER .ENDC ; DF K$$MLP .PAGE .SBTTL . - DEVICE NOT READY MESSAGE PROCESSOR ; PROCESS DEVICE NOT READY MESSAGES DEVNR: ; REF LABEL .IF DF T$$KMG MOV #T.NDNR,R0 ; SET FOR DEVICE NOT READY MESSAGE .IFTF ; DF T$$KMG MOVB #1,S.CTM(R4) ; SET TIMEOUT FOR 1 SECOND .IFT ; DF T$$KMG DECB S.STS(R4) ; TIME TO OUTPUT MESSAGE ? BNE 120$ ; IF NE, NO .IF NDF L$$PTO MOVB #15.,S.STS(R4) ; SET TO OUTPUT NEXT MESSAGE IN ; 15. SECONDS .IFF ; NDF L$$PTO MOVB #L$$PTO,S.STS(R4) ; SET TO OUTPUT NEXT MESSAGE IN ; L$$PTO SECONDS BNE 110$ ; IF NE, LP NOT READY MESSAGES ENABLED INCB S.STS(R4) ; LP NOT READY MESSAGE NOT WANTED, SO BR 120$ ; RE-BUSY CONTROLLER .ENDC ; NDF L$$PTO 110$: CALLR @DVMSG ; OUTPUT MESSAGE .ENDC ; DF T$$KMG 120$: RETURN ; OUT ! .DSABL LSB .PAGE .SBTTL LPCAN - LINE PRINTER CANCEL ENTRY POINT ; ; CANCEL I/O OPERATION-FORCE I/O TO COMPLETE IF DEVICE IS NOT READY ; LPCAN: CMP R1,I.TCB(R0) ;;; REQUEST FOR CURRENT TASK? BNE 10$ ;;; IF NE, NO BIS #ABRT,U.CW2(R5) ;;; SET FOR ABORT IF DEVICE NOT READY .IF DF K$$MLP BIT #KP.OFL,S.KTB+2(R4) ;;; VERIFY PORT IS ONLINE BNE 10$ ;;; IF NE, IT'S OFFLINE MOV S.KTB+2(R4),R0 ;;; GET ADDRESS OF KMC11 BEQ 10$ ;;; IF EQ, THIS PRINTER NOT ON KMC BIT #KMCLOA,K.PRM(R0) ;;; IS THE MICROCODE LOADED FOR THE KMC? BEQ 10$ ;;; IF EQ, NO MOVB #1,S.CTM(R4) ;;; FORCE TIMEOUT IN 1 SECOND (OR LESS) .ENDC ; DF K$$MLP 10$: RETURN ;;; .PAGE .SBTTL LPKRB - KRB STATUS CHANGE ENTRY POINT ; ON ENTRY: ; ; R3 = CTB ADDRESS FOR THE CONTROLLER ; R2 = KRB ADDRESS FOR THE CONTROLLER ; 0(SP) = RETURN ADDRESS FOR COMPLETION ; 2(SP) = RETURN ADDRESS FOR CALLER OF THE EXEC ROUTINE ; ; C = 0 IF THE CALL IS FOR CONTROLLER ONLINE ; C = 1 IF THE CALL IS FOR CONTROLLER OFFLINE ; ; $SCERR IS PRESET TO 1 ; LPKRB: ; CONTROLLER STATUS CHANGE ENTRY POINT ; AND EXEC VECTOR TRANSLATE ROUTINE .IF DF K$$MLP BCS 25$ ; BR IF CONTROLLER OFFLINE .IFTF ; DF K$$MLP ; FILL IN EXEC VECTOR IF WE HAVEN'T DONE SO ALREADY TST EXEVEC ; EXEC VECTOR TRANSLATED ? BNE 15$ ; IF NE, YES - DON'T REPEAT. MOV R3,-(SP) ; SAVE A REGISTER MOV R2,-(SP) ; OR TWO MOV @#112,R0 ; R0 > TABLE OF ENTRIES MOV (R0),R0 ; AND APR BIAS (1ST WORD OF TABLE). MOV KINAR6,-(SP) ; SAVE I-SPACE MAPPING. MOV (R0),KINAR6 ; MAP COMMON THROUGH I-SPACE APR6. MOV #EXEVEC,R3 ; R3 > EXEC VECTOR AND MOV #EXEVCL,R2 ; R2 = LENGTH OF VECTOR AREA. CALL @#140004 ; TRANSLATE THE VECTORS. MOV (SP)+,KINAR6 ; RESTORE I-SPACE MAPPING. MOV (SP)+,R2 ; RESTORE MOV (SP)+,R3 ; REGISTERS 15$: ; REFERENCE LABEL .IFT ; DF K$$MLP BIT #KPKMC,K.PRM(R2); IS THIS A KMC KRB? BEQ 40$ ; IF EQ, NO, JUST RETURN MOV R3,KMCCTB ; SAVE LOCATION OF CTB MOV R2,R4 ; PUT KRB INTO R4 MOV #0,R5 ; MICROCODE FILENAME INDEX CALL @ULDRQ ; REQUEST THE MICROCODE LOADER BCC 40$ ; BR IF SUCCESSFUL BNE 30$ ; IF NE, NO POOL, REJECT ONLINE TRANSITION 20$: MOVB #IE.NST,@SCERR ; MICROCODE LOADER NOT INSTALLED BR 40$ ; AND RETURN 25$: BIT #KPKMC,K.PRM(R2) ; IS THIS A KMC KRB BEQ 40$ ; IF EQ, NO, JUST RETURN BIC #KMCLOA,K.PRM(R2) ; CLEAR MICROCODE LOADED BIT MOV #MC,@(R2) ; MASTER CLEAR KMC-11 BR 40$ ; 30$: MOVB #IE.NOD,@SCERR ; INDICATE NO POOL .IFTF ; DF K$$MLP 40$: RETURN .IFT ; DF K$$MLP .PAGE .SBTTL LPUCB - UCB STATUS CHANGE ENTRY POINT ; ON ENTRY: ; ; R5 = ADDRESS OF UCB OR UNIT CHANGIN STATUS ; R4 = ADDRESS OF SCB OF UNIT ; R3 = CONTROLLER INDEX (UNDEFINED IF S.KRB=0) ; 0(SP) = RETURN ADDRESS FOR COMPLETION ; 2(SP) = RETURN ADDRESS FOR CALLER OF THE EXEC ROUTINE ; ; C = 0 IF THE CALL IS FOR CONTROLLER ONLINE ; C = 1 IF THE CALL IS FOR CONTROLLER OFFLINE ; ; $SCERR IS PRESET TO 1 LPUCB: BCS 10$ ; BR IF OFFLINE BIT #1,S.KTB(R4) ; IS THE LP PORT ONLINE BEQ 10$ ; IF EQ, YES, ITS OK MOVB #IE.CNR,@SCERR ; REJECT TRANSITION 10$: BIC #KNOWN,U.CW2(R5) ; SET PRINTER UNKNOWN RETURN .ENDC ; DF K$$MLP .PAGE .SBTTL . SUBROUTINES ; ; SUBROUTINE TO FILL LINE PRINTER BUFFER ; LPRNT: MOV @S.KRB(R4),R1 ; GET CSR ADDRESS MOV U.BUF+2(R5),R0 ; GET ADDRESS OF USER BUFFER .IF DF M$$MGE MOV U.BUF(R5),@KISA6 ; MAP TO USER BUFFER .IFTF 5$: MOV #5,R2 ; SET LOOP COUNT 10$: TST (R1) ; TEST ERROR BPL 20$ ; BRANCH IF NO ERROR MOV R5,R3 ; CALCULATE ADDRESS OF RELOCATION BIAS ADD #U.BUF,R3 ; MOV S.PKT(R4),R1 ; GET ADDRESS OF I/O PACKET ADD #I.PRM,R1 ; POINT TO RELOCATION BIAS MOV (R1)+,(R3)+ ; RESET RELOCATION BIAS MOV (R1)+,(R3)+ ; RESET BUFFER ADDRESS MOV (R1),(R3) ; RESET BYTE COUNT SEC ; RETURN ; 20$: TSTB (R1) ; TEST BIT READY BMI 40$ ; DEC R2 ; BNE 10$ ; LOOP AGAIN SEC ; SET BIT CARRY 30$: MOV R0,U.BUF+2(R5) ; SAVE ADDRESS OF NEXT BYTE IN USER BUFFER .IFT MOV @KISA6,U.BUF(R5) ; SAVE MAPPING INFORMATION .ENDC RETURN ; 35$: TST -(R3) ; ADJUST TO PRINTER STATUS WORD 40$: BIT #FORM!LFCT!BHLD!BLCT,(R3) ; FORM, LINE FEED, BYTE HELD, OR BLANK BEQ 50$ ; IF EQ, NO BIT #BLCT,(R3) ; ANY BLANKS TO BE OUTPUT? BNE 80$ ; IF NE, YES BIT #BHLD,(R3) ; BYTE HELD BACK FOR CARRIAGE RETURN? BNE 65$ ; IF NE, YES BIT #FORM,(R3) ; FORM FEED TO BE OUTPUT? BNE 60$ ; IF NE, YES SUB #LFBT,(R3)+ ; REDUCE LINE FEED COUNT MOVB #12,R2 ; SET TO OUTPUT A LINE FEED BR 100$ ; 50$: TST U.CNT(R5) ; ANY MORE BYTES TO OUTPUT? BNE 70$ ; IF NE, YES BIT #CRTY,(R3) ; CARIAGE RETURN AT END OF LINE? BEQ 30$ ; IF EQ, NO BIC #CRTY,(R3)+ ; CLEAR CARRIAGE RETURN BIT MOVB #15,R2 ; SET TO OUTPUT A CARRIAGE RETURN BR 100$ ; 60$: BIC #FORM,(R3)+ ; CLEAR FORM FEED BIT MOVB #14,R2 ; SET TO OUTPUT A FORM FEED BR 100$ ; 65$: BIC #BHLD,(R3) ; CLEAR BYTE HELD FOR CARRIAGE RETURN MOVB 3(R3),R2 ; RETRIEVE HELD BYTE BR 150$ ; 70$: MOVB (R0)+,R2 ; GET NEXT BYTE FROM USER BUFFER .IF DF M$$MGE BIT #20000,R0 ; OVERFLOW 4K BOUNDRY? BEQ 75$ ; IF EQ, NO BIC #20000,R0 ; CLEAR OVERFLOW BIT ADD #200,@KISA6 ; UPDATE RELOCATION BIAS .ENDC 75$: DEC U.CNT(R5) ; DECREMENT BYTE COUNT CMPB #177,R2 ; RUBOUT? BEQ 50$ ; IF EQ, YES TST (R3)+ ; ADJUST TO HORIZONAL POSITION CMPB #11,R2 ; HORIZONAL TAB? BNE 90$ ; IF NE, NO MOVB (R3),-(SP) ; GET CURRENT HORIZONAL POSITION BIS #177770,(SP) ; CALCULATE BLANK COUNT TO NEXT TAB STOP NEG (SP) ; BIS (SP)+,-(R3) ; SET BLANK COUNT 80$: DEC (R3)+ ; REDUCE BLANK COUNT MOVB #' ,R2 ; SET TO OUTPUT A BLANK 90$: BHI 110$ ; IF HI, OUTPUT BYTE CMPB #15,R2 ; LF, CR, VT, OR FF? BLO 110$ ; IF LO, NO CMPB #13,R2 ; VERTICLE TAB? BEQ 110$ ; IF EQ, YES 100$: CLRB (R3) ; CLEAR HORIZONAL POSITION BR 120$ ; 110$: CMPB (R3),U.CW4(R5) ; CARRIAGE OVERFLOW? BHIS 35$ ; IF HIS, YES INCB (R3) ; INCREMENT HORIZONAL POSITION 120$: TST -(R3) ; LS11 PRINTER? .IF DF L$$11R BMI 150$ ; IF MI, YES CMPB R2,#15 ; CARRIAGE RETURN? BHI 130$ ; IF HI, NO BEQ 160$ ; IF EQ, YES CMPB R2,#14 ; FORM FEED? BEQ 140$ ; IF EQ, YES CMPB R2,#12 ; LINE FEED? BEQ 140$ ; IF EQ, YES 130$: BIT #CRJT,(R3) ; CARRIAGE RETURN JUST OUTPUT? BEQ 150$ ; IF EQ, NO BIS #BHLD,(R3) ; SET BYTE HELD BACK FOR CARRIAGE RETURN MOVB R2,3(R3) ; SAVE BYTE HELD BACK MOVB #15,R2 ; SET TO OUTPUT CARRIAGE RETURN 140$: BIC #CRJT,(R3) ; CLEAR CARRIAGE RETURN JUST OUTPUT .IFTF ; ; TEST THE PRINTER CASE INDICATION IN CW2 ; IF IT DOES NOT INDICATE LOWER CASE ; FORCE LOWER CASE CHARACTERS TO UPPER CASE ; 150$: BIT #LOWER,U.CW2(R5) ; LOWER CASE PRINTER? BNE 155$ ; IF NE, YES, SKIP CONVERT CMPB #141,R2 ; 'a' OR ABOVE BHI 155$ ; IF HI, NO CMPB #172,R2 ; YES, 'z' OR BELOW BLO 155$ ; IF LO, NO BIC #40,R2 ; YES, CONVERT IT 155$: MOVB R2,2(R1) ; OUTPUT BYTE JMP 5$ ; GO AGAIN .IFT 160$: BIS #CRJT,(R3) ; SET CARRIAGE RETURN JUST OUTPUT JMP 5$ ; .ENDC ; ; SUBROUTINE TO WAIT FOR THE KMC TO BE READY ; ; INPUTS: ; ; R5 = UCB ADDRESS OF THE PRINTER ; R4 = SCB ADDRESS OF THE PRINTER ; ; OUTPUTS: ; ; R0 = KMC CSR ADDRESS .IF DF K$$MLP WTKMC: MOV @S.KTB+2(R4),R0 ; GET KMC CSR ADDRESS BIS #RQI,(R0) ; REQUEST KMC INPUT 10$: TST (R0) ; IS THE KMC-11 RUNNING ? BPL 20$ ; IF PL, KMC NOT RUNNING - POWERFAIL BIT #RDYI,2(R0) ; READY BIT SET ? BEQ 10$ ; IF EQ, NO, WAIT SOME MORE BIC #RQI,(R0) ; CLEAR REQUEST INPUT RETURN ; YES, BO BACK ; ; WE WERE WAITING FOR THE KMC BUT THE KMC IS NOT RUNNING. THEREFORE, ; WE WILL GO TO THE POWERFAIL CODE WHICH WILL REQUEST THE MICROCODE LOADER ; TO RELOAD THE MICROCODE TO THE KMC. IF UNSUCCESSFUL, WE WILL CONTINUE ; PRINTING WITHOUT THE KMC. ; 20$: BIS #PWRFLG!RQINPR,U.CW2(R5) ; SET POWERFAIL IN PROGRESS TST (SP)+ ; WE WON'T BE RETURNING TO CALLER MOV S.KTB+2(R4),R2 ; GET KRB ADDRESS MOV KMCCTB,R3 ; GET CTB ADDRESS JMP LKPWF0 ; FINISH IN COMMON CODE .ENDC ; DF K$$MLP .END